using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
#if !PocketPC && Framework20
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
#endif

namespace GeoFramework.IO.Bluetooth
{
#if !PocketPC && Framework20
    [SuppressUnmanagedCodeSecurity]
#endif
    internal 
#if Framework20
		static 
#else
		sealed
#endif	
	class NativeMethods
	{
		//private NativeMethods(){}

		private const int LPTR = 0x42;

		//CE 5.0
        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthAcceptSCOConnections(int fAccept);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthAuthenticate(byte[] pbt);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthCancelInquiry();

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthClearInquiryFilter();

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthCloseConnection(ushort handle);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthCreateACLConnection(byte[] pbt, ref ushort phandle);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthCreateSCOConnection(byte[] pbt,ref ushort phandle);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthEnterHoldMode(byte[] pba, ushort hold_mode_max, ushort hold_mode_min, ref ushort pinterval);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthEnterParkMode(byte[] pba, ushort beacon_max, ushort beacon_min, ref ushort pinterval);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthEnterSniffMode(byte[] pba, ushort sniff_mode_max, ushort sniff_mode_min, ushort sniff_attempt, ushort sniff_timeout, ref ushort pinterval);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthExitParkMode(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthExitSniffMode(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetAddress(ushort handle, byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetBasebandConnections(int cConnections, byte[] pConnections, ref int pcConnectionsReturned);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetBasebandHandles(int cHandles, ref ushort pHandles, ref int pcHandlesReturned);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetCurrentMode(byte[] pba, ref byte pmode);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetHardwareStatus(ref HardwareStatus pistatus);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetLinkKey(byte[] pba, ref Guid key);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetPINRequest(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthGetRemoteCOD(byte[] pbt, ref uint pcod);

		//CE 5.0
        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthPairRequest(byte[] pba, int cPinLength, byte[] ppin);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthPerformInquiry(
        //    uint LAP,
        //    byte length,
        //    byte num_responses,
        //    uint cBuffer,
        //    ref uint pcDiscoveredDevices,
        //    byte[] InquiryList);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadAuthenticationEnable(ref byte pae);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadCOD(ref uint pcod);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadLinkPolicySettings(byte[] pba, ref ushort plps);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadLocalAddr(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadLocalVersion(
        //    ref byte phci_version,
        //    ref ushort phci_revision,
        //    ref byte plmp_version,
        //    ref ushort plmp_subversion,
        //    ref ushort pmanufacturer,
        //    ref byte plmp_features);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadPageTimeout(ref ushort ptimeout);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadRemoteVersion(
        //    byte[] pba,
        //    ref byte plmp_version,
        //    ref ushort plmp_subversion,
        //    ref ushort pmanufacturer,
        //    ref byte plmp_features);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthReadScanEnableMask(ref byte pmask);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthRefusePINRequest(byte[] pbt);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthRemoteNameQuery(
        //    byte[] pba,
        //    uint cBuffer,
        //    ref uint pcRequired,
        //    byte[] szString);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthRevokeLinkKey(byte[] pba);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthRevokePIN(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthSetEncryption(byte[] pba, int fOn);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthSetInquiryFilter(byte[] pba);

        //[DllImport("Btdrt.dll", SetLastError=true)]
        //public static extern int BthSetLinkKey(byte[] pba, ref Guid key);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthSetPIN(byte[] pba, int cPinLength, byte[] ppin);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthSetSecurityUI(IntPtr hEvent, int dwStoreTimeout, int dwProcTimeout);
		
        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthTerminateIdleConnections();

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthWriteAuthenticationEnable(byte ae);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthWriteCOD(uint cod);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthWriteLinkPolicySettings(byte[] pba,	ushort lps);

        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthWritePageTimeout(ushort timeout);
		
        //[DllImport("btdrt.dll", SetLastError=true)]
        //public static extern int BthWriteScanEnableMask(byte mask);


#if PocketPC
		// Utils
        [DllImport("BthUtil.dll", SetLastError=true)]
        public static extern int BthSetMode(RadioMode dwMode);

        [DllImport("BthUtil.dll", SetLastError=true)]
        public static extern int BthGetMode(ref RadioMode dwMode);
#endif
		

		//GetLastError
        //[DllImport("ws2.dll", EntryPoint="WSAGetLastError", SetLastError=true)]
        //public static extern int CeGetLastError();
        //[DllImport("ws2_32.dll", EntryPoint="WSAGetLastError", SetLastError=true)]
        //public static extern int XpGetLastError();


		//SetService
        //[DllImport("ws2.dll", EntryPoint="WSASetService", SetLastError=true)]
        //public static extern int CeSetService(
        //    byte[] lpqsRegInfo,
        //    WSAESETSERVICEOP essoperation,
        //    int dwControlFlags);
        //[DllImport("ws2_32.dll", EntryPoint="WSASetService", SetLastError=true)]
        //public static extern int XpSetService(
        //    byte[] lpqsRegInfo,
        //    WSAESETSERVICEOP essoperation,
        //    int dwControlFlags);

#if !PocketPC
		[SuppressUnmanagedCodeSecurity()] 
#endif
        public static int LookupServiceBegin(WSAQUERYSET pQuerySet, LookupFlags dwFlags, out IntPtr lphLookup)
        {
#if PocketPC
				if(Environment.OSVersion.Platform == System.PlatformID.WinCE)
                    return LookupServiceBeginCompact(pQuerySet, dwFlags, out lphLookup);
				else
#endif
                    return LookupServiceBeginDesktop(pQuerySet, dwFlags, out lphLookup);
        }

#if !PocketPC
        [SuppressUnmanagedCodeSecurity()] 
#endif
        public static int LookupServiceNext(IntPtr hLookup, LookupFlags dwFlags, ref int lpdwBufferLength, byte[] pResults)
        {
#if PocketPC
				if(Environment.OSVersion.Platform == System.PlatformID.WinCE)
					return LookupServiceNextCompact(hLookup, dwFlags, ref lpdwBufferLength, pResults);
				else
#endif
            return LookupServiceNextDesktop(hLookup, dwFlags, ref lpdwBufferLength, pResults);
        }

#if !PocketPC
        [SuppressUnmanagedCodeSecurity()] 
#endif
        public static int WsaGetLastError()
        {
#if PocketPC
            if (Environment.OSVersion.Platform == System.PlatformID.WinCE)
                return WsaGetLastErrorCompact();
            else
#endif
                return WsaGetLastErrorDesktop();
        }

#if !PocketPC
        [SuppressUnmanagedCodeSecurity()] 
#endif
        public static int LookupServiceEnd(IntPtr hLookup)
        {
#if PocketPC
				if(Environment.OSVersion.Platform == System.PlatformID.WinCE)
					return LookupServiceEndCompact(hLookup);
				else
#endif
            return LookupServiceEndDesktop(hLookup);
        }

		// LookupService
#if PocketPC
        [DllImport("ws2.dll", EntryPoint="WSALookupServiceBegin", SetLastError=true)]
        private static extern int LookupServiceBeginCompact(
            WSAQUERYSET pQuerySet,
            LookupFlags dwFlags,
            out IntPtr lphLookup);

        [DllImport("ws2.dll", EntryPoint="WSALookupServiceNext", SetLastError=true)]
        private static extern int LookupServiceNextCompact(
            IntPtr hLookup,
            LookupFlags dwFlags,
            ref int lpdwBufferLength,
            byte[] pResults);

        [DllImport("ws2.dll", EntryPoint="WSALookupServiceEnd", SetLastError=true)]
        public static extern int LookupServiceEndCompact(
            IntPtr hLookup);

        [DllImport("ws2.dll", EntryPoint = "WSAGetLastError", SetLastError = true)]
        private static extern int WsaGetLastErrorCompact();
#endif

        [DllImport("Ws2_32.dll", EntryPoint="WSALookupServiceBegin", SetLastError=true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        private static extern int LookupServiceBeginDesktop(
            WSAQUERYSET pQuerySet, 
            LookupFlags dwFlags,
            out IntPtr lphLookup);

        [DllImport("Ws2_32.dll", EntryPoint="WSALookupServiceNext", SetLastError=true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        private static extern int LookupServiceNextDesktop(IntPtr hLookup, LookupFlags dwFlags, ref int lpdwBufferLength, byte[] pResults);

        [DllImport("Ws2_32.dll", EntryPoint="WSALookupServiceEnd", SetLastError=true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern int LookupServiceEndDesktop(IntPtr hLookup);


        [DllImport("Ws2_32.dll", EntryPoint = "WSAGetLastError", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern int WsaGetLastErrorDesktop();


        ////desktop methods
        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif        
        public static extern bool BluetoothIsConnectable(IntPtr hRadio);

        [DllImport("Irprops.cpl", SetLastError = true)]
      #if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern bool BluetoothIsDiscoverable(IntPtr hRadio);

        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern bool BluetoothEnableDiscovery(IntPtr hRadio, bool fEnabled);

        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern bool BluetoothEnableIncomingConnections(IntPtr hRadio, bool fEnabled);

        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern IntPtr BluetoothFindFirstRadio(
            ref BLUETOOTH_FIND_RADIO_PARAMS pbtfrp,
            ref IntPtr phRadio);

        //[DllImport("Irprops.cpl", SetLastError = true)]
        //public static extern bool BluetoothFindNextRadio(IntPtr hFind, ref IntPtr phRadio);

        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern bool BluetoothFindRadioClose(IntPtr hFind);

        [DllImport("Irprops.cpl", SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        public static extern int BluetoothGetRadioInfo(IntPtr hRadio, byte[] pRadioInfo);

        //[DllImport("coredll.dll", SetLastError=true)]
        //public static extern int LocalFree(IntPtr ptr);
	}

#if PocketPC
	[StructLayout(LayoutKind.Sequential)]
#else
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
#endif
    internal class WSAQUERYSET
    {
        public Int32 dwSize = 0;
        public string szServiceInstanceName = null;
        public IntPtr lpServiceClassId;
        public IntPtr lpVersion;
        public string lpszComment;
        public Int32 dwNameSpace;
        public IntPtr lpNSProviderId;
        public string lpszContext;
        public Int32 dwNumberOfProtocols;
        public IntPtr lpafpProtocols;
        public string lpszQueryString;
        public Int32 dwNumberOfCsAddrs;
        public IntPtr lpcsaBuffer;
        public Int32 dwOutputFlags;
        public IntPtr Blob;
    }

	internal enum WSAESETSERVICEOP : int
	{
		/// <summary>
		/// Register the service. For SAP, this means sending out a periodic broadcast.
		/// This is an NOP for the DNS namespace.
		/// For persistent data stores, this means updating the address information. 
		/// </summary>
		RNRSERVICE_REGISTER = 0,
		/// <summary>
		///  Remove the service from the registry.
		///  For SAP, this means stop sending out the periodic broadcast.
		///  This is an NOP for the DNS namespace.
		///  For persistent data stores this means deleting address information. 
		/// </summary>
		RNRSERVICE_DEREGISTER,
		/// <summary>
		/// Delete the service from dynamic name and persistent spaces.
		/// For services represented by multiple CSADDR_INFO structures (using the SERVICE_MULTIPLE flag), only the specified address will be deleted, and this must match exactly the corresponding CSADDR_INFO structure that was specified when the service was registered 
		/// </summary>
		RNRSERVICE_DELETE, 

	}

	[Flags()]
	internal enum LookupFlags : uint
	{
		LUP_DEEP                = 0x0001,
		LUP_CONTAINERS          = 0x0002,
		LUP_NOCONTAINERS        = 0x0004,
		LUP_NEAREST             = 0x0008,
		LUP_RETURN_NAME         = 0x0010,
		LUP_RETURN_TYPE         = 0x0020,
		LUP_RETURN_VERSION      = 0x0040,
		LUP_RETURN_COMMENT      = 0x0080,
		LUP_RETURN_ADDR         = 0x0100,
		LUP_RETURN_BLOB         = 0x0200,
		LUP_RETURN_ALIASES      = 0x0400,
		LUP_RETURN_QUERY_STRING = 0x0800,
		LUP_RETURN_ALL          = 0x0FF0,
		LUP_RES_SERVICE         = 0x8000,
		LUP_FLUSHCACHE			= 0x1000,
		LUP_FLUSHPREVIOUS		= 0x2000
	}

	[Flags()]
	internal enum ScanMask : byte
	{
		None = 0,
		Inquiry = 1,
		Page = 2,
	}
}
